package tetris;

import java.awt.Color;

public class GeneticAI extends TetrisAI
{

    private double[] disc = null;
    double sum = 0;

    @Override
    double rateBoard(Color[][] board)
    {
        int maxHeight = getMaxHeight(board);
        int colDiff = columnDifference(board);
        int holes = getHoles(board);
        int wells = getWells(board, maxHeight);
        int linesMade = linesMade(board, maxHeight);
        int edges = getEdges(board);
        int edgesTouchingWalls = getEdgesTouchingWalls(board);
        int boardHorizon = boardHorizon(board, maxHeight);
        int rowTransition = getRowTransitions(board);
        int columnTransition = getColumnTransitions(board);
        int penalizeHeight = penalizeHeight(board, maxHeight);

        double weight;
        weight = maxHeight * disc[0] + colDiff * disc[1] + holes * disc[2]
                + wells * disc[3] - linesMade * disc[4] - edges * disc[5]
                - edgesTouchingWalls * disc[6] + boardHorizon * disc[7]
                + rowTransition * disc[8] + columnTransition * disc[9]
                + penalizeHeight * disc[10];

        return weight / 100;
    }

    public void setDisc(double[] disc)
    {
        this.disc = disc.clone();
    }

    private int getRowTransitions(Color[][] board)
    {
        int transitions = 0;
        boolean trans = false;

        for (int h = 0; h < board.length; h++) {
            if (board[h][0] == null) {
                trans = true;
            } else {
                trans = false;
            }
            for (int w = 0; w < board[0].length; w++) {
                if (trans == false && board[h][w] == null) {
                    transitions++;
                    trans = true;
                } else if (trans == true && board[h][w] != null) {
                    transitions++;
                    trans = false;
                }
            }
        }

        return transitions;
    }

    private int getColumnTransitions(Color[][] board)
    {
        int transitions = 0;
        boolean trans = false;

        for (int w = 0; w < board[0].length; w++) {
            if (board[0][w] == null) {
                trans = true;
            } else {
                trans = false;
            }
            for (int h = 0; h < board.length; h++) {
                if (trans == false && board[h][w] == null) {
                    transitions++;
                    trans = true;
                } else if (trans == true && board[h][w] != null) {
                    transitions++;
                    trans = false;
                }
            }
        }

        return transitions;
    }

    private int columnDifference(Color[][] board)
    {
        int diff = 0;
        int colHeight = 0;
        int colHeight2 = 0;

        for (int w = 0; w < board[0].length; w++) {
            if (w + 1 < board[0].length) {
                colHeight = getColumnHeight(board, w);
                colHeight2 = getColumnHeight(board, w + 1);

                if (colHeight > colHeight2) {
                    diff += colHeight - colHeight2;
                } else {
                    diff += colHeight2 - colHeight;
                }
            }
        }

        return diff;
    }

    private int getColumnHeight(Color[][] board, int column)
    {
        for (int h = 0; h < board.length; h++) {
            if (board[h][column] != null) {
                return board.length - h;
            }
        }

        return 0;
    }

    private int getHoles(Color[][] board)
    {
        int holes = 0;

        for (int w = 0; w < board[0].length; w++) {
            holes += getColumnHoles(board, w);
        }

        return holes;
    }

    private int getColumnHoles(Color[][] board, int column)
    {
        boolean roof = false;
        int holes = 0;

        for (int h = 0; h < board.length; h++) {
            if (board[h][column] != null) {
                roof = true;
            }

            if (roof == true && board[h][column] == null) {
                holes++;
            }
        }

        return holes;
    }

    private int getWells(Color[][] board, int maxHeight)
    {
        int wells = 0;

        for (int w = 0; w < board[0].length; w++) {
            for (int h = board.length - maxHeight; h < board.length; h++) {
                if (board[h][w] == null) {
                    wells++;
                }
            }
        }

        return wells;
    }

    private int boardHorizon(Color[][] board, int maxHeight)
    {
        int horizon = 0;

        for (int w = 0; w < board[0].length; w++) {
            for (int h = 0; h < board.length; h++) {
                if (board[h][w] != null) {
                    horizon += board.length - h;
                    break;
                }
            }
        }
        horizon /= 10;
        return horizon;
    }

    private int getMaxHeight(Color[][] board)
    {
        int height = board.length;
        int maxHeight = 0;
        for (int h = 0; h < board.length; h++) {
            for (int w = 0; w < board[0].length; w++) {
                if (board[h][w] != null) {
                    if (height - h > maxHeight) {
                        maxHeight = height - h;
                    }
                    break;
                }
            }
        }
        return maxHeight;
    }

    private int getEdgesTouchingWalls(Color[][] board)
    {
        int edges = 0;

        for (int h = 0; h < board.length; h++) {
            if (board[h][0] != null) {
                edges++;
            }
            if (board[h][board[0].length - 1] != null) {
                edges++;
            }
        }

        return edges;
    }

    private int getEdges(Color[][] board)
    {
        int edges = 0;


        for (int w = 0; w < board[0].length; w++) {
            for (int h = 0; h < board.length; h++) {
                if (board[h][w] != null) {
                    if ((h + 1) >= board.length) {
                        edges++;
                    } else if (board[h + 1][w] != null) {
                        edges++;
                    }

                    if ((h - 1) < 0) {
                        edges++;
                    } else if (board[h - 1][w] != null) {
                        edges++;
                    }

                    if ((w + 1) >= board[0].length) {
                        edges++;
                    } else if (board[h][w + 1] != null) {
                        edges++;
                    }

                    if ((w - 1) < 0) {
                        edges++;
                    } else if (board[h][w - 1] != null) {
                        edges++;
                    }
                }
            }
        }

        return edges;
    }

    private int linesMade(Color[][] board, int maxHeight)
    {
        int nrOfLines = 0;
        int count = 0;
        for (int h = board.length - maxHeight; h < board.length; h++) {
            for (int w = 0; w < board[0].length; w++) {
                if (board[h][w] != null) {
                    count++;
                }
            }

            if (count == 10) {
                nrOfLines++;
            }
            count = 0;
        }
        return nrOfLines;
    }

    private int penalizeHeight(Color[][] board, int maxHeight)
    {
        int sum = 0;
        for (int h = 0; h < board.length; h++) {
            for (int w = 0; w < board[0].length; w++) {
                if (board[h][w] != null) {
                    sum += board.length - h;
                }
            }

        }

        return sum;
    }
}
